package com.example.template.jdbc;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public abstract class JdbcTemplate {

    private DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] params) {

        try (Connection connection = getConnection(dataSource);
             PreparedStatement prepareStatement = createPrepareStatement(connection, sql);
             ResultSet resultSet = this.executeQuery(prepareStatement, params);) {

            List<?> result = this.parseResultSet(resultSet, rowMapper);
            return result;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    protected  List<?> parseResultSet(ResultSet resultSet, RowMapper<?> rowMapper) throws SQLException {
        List<Object> result = new ArrayList<Object>();
        int rowNum=1;
        while (resultSet.next()) {
            result.add(rowMapper.mapRow(resultSet, rowNum++));
        }
        return result;
    }

    protected ResultSet executeQuery(PreparedStatement prepareStatement, Object[] params) throws SQLException {
        for (int i = 0; i < params.length; i++) {
            prepareStatement.setObject(i, params[i]);
        }
        ResultSet resultSet = prepareStatement.executeQuery();
        return resultSet;
    }

    private PreparedStatement createPrepareStatement(Connection connection, String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    private Connection getConnection(DataSource dataSource) throws SQLException {
        return dataSource.getConnection();
    }

}
